package com.example.retry.mock;

import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Function;

public enum MockStrategyEnum {
	OK("OK") {
		@Override
		public <R, T> Optional<R> mock(Function<T, R> f, T input, List<R> availableList) {
			if (f != null) {
				// 执行业务逻辑
				return Optional.of(f.apply(input));
			} else if (null != availableList && !availableList.isEmpty()) {
				return Optional.of(availableList.get(0));
			}
			return Optional.empty();
		}
	},
	RANDOM("RANDOM") {
		@Override
		public <R, T> Optional<R> mock(Function<T, R> f, T input, List<R> availableList) {
			Random random = new Random();
			if (null != availableList && !availableList.isEmpty()) {
				return Optional.of(availableList.get(random.nextInt(availableList.size())));
			} else {
				if (random.nextInt(2) == 0) {
					throw new RuntimeException("抛出的Mock异常");
				}
			}
			return Optional.empty();
		}
	},
	FAILED("FAILED") {
		@Override
		public <R, T> Optional<R> mock(Function<T, R> f, T input, List<R> availableList) {
			return Optional.empty();
		}
	},
	EXCEPTION("EXCEPTION") {
		@Override
		public <R, T> Optional<R> mock(Function<T, R> f, T input, List<R> availableList) {
			throw new RuntimeException("抛出的Mock异常");
		}
	};

	private String code;

	MockStrategyEnum(String code) {
		this.code = code;
	}

	public abstract <R, T> Optional<R> mock(Function<T, R> f, T input, List<R> available);

	public static MockStrategyEnum of(String code) {
		for (MockStrategyEnum elem : MockStrategyEnum.values()) {
			if (elem.code.equalsIgnoreCase(code)) {
				return elem;
			}
		}
		return FAILED;
	};

}
